%{

#include "commonXML.h"

int xmlwrap(void);
void xmlerror(XML** xml, char *msg);
int xmllex(void);
%}

%union {
   char * s;
   ElementName * en;  /* le nom d'un element avec son namespace */
   vector<AttributeXML*> * liste_attr;
   AttributeXML *  attribut_t;
   vector<NodeXML *> * liste_nodes;
   ElementXML * elem;
   XML * xml_t;
}

%token EQ SLASH CLOSE CLOSESPECIAL DOCTYPE XSLSTYLESHEET
%token <s> ENCODING STRING DATA COMMENT IDENT NSIDENT
%token <en> NSSTART START STARTSPECIAL END NSEND

%type <liste_attr> attribut_opt
%type <liste_nodes> empty_or_content
%type <liste_nodes> close_content_and_end
%type <liste_nodes> content_opt
%type <elem> xml_element
%type <en> start
%type <s> declaration
%type <s> declarations_opt
%type <s> declarations_opt_xsl
%type <s> declaration_xsl
%type <attribut_t> attribut
%type <xml_t> document

%parse-param{XML ** xml}
%%

document
 : declarations_opt_xsl declarations_opt xml_element misc_seq_opt {*xml = new XML($2,$3);}//{ cout << $2->toString() ; }
 ;

misc_seq_opt
 : misc_seq_opt comment
 | /*empty*/
 ;

comment
 : COMMENT
 ;

declarations_opt_xsl
 : declaration_xsl { $$ = $1 ;}
 | /*empty*/{ $$ = NULL ;}
 ;

declaration_xsl
 : XSLSTYLESHEET attribut attribut CLOSESPECIAL {$$ = NULL;}
 ;

declarations_opt
 : declaration {$$ = $1;}
 | /*empty*/{ $$ = NULL;}
 ;

declaration
 : DOCTYPE IDENT IDENT STRING CLOSE {$$ = $4;}//{ *xml = new XML; *xml->setDTD($4); }
 ;

attribut
 : IDENT EQ STRING { $$ = new AttributeXML($1,$3); }
 | NSIDENT EQ STRING { $$ = new AttributeXML($1,$3); }
;

attribut_opt
 : attribut_opt attribut { $$ = $1; $$->push_back($2);  }
 | /*empty*/ { $$ = new vector<AttributeXML * >; } 
 ;

xml_element
 : start attribut_opt empty_or_content { $$ = new ElementXML(($3), ($2), $1->first,$1->second); }
 ;
start
 : START { $$ = $1;} 
 | NSSTART { $$ = $1;} 
 ;
empty_or_content
 : SLASH CLOSE { $$ = new vector<NodeXML *>; }
 | close_content_and_end CLOSE {$$ = $1}
 ;
close_content_and_end
 : CLOSE content_opt END {$$ = $2}
 | CLOSE content_opt NSEND {$$ = $2}
 ;
content_opt 
 : content_opt DATA { $$ = $1; $$->push_back(new TextXML($2));}
 | content_opt comment {$$=$1;}//On ignore les commentaires
 | content_opt xml_element { $$ = $1; $$->push_back($2);}
 | /*empty*/ { $$ = new vector<NodeXML *>; }
 ;
%%


int xmlwrap(void)
{
  return 1;
}


void xmlerror(XML ** xml,char *msg)

{
  fprintf(stderr, "%s\n", msg);
}
